[AIFFEL] CV_고양이수염붙이기
by SuJin
import cv2
import dlib
print(cv2.__version__)
print(dlib.__version__)
4.5.3 19.22.1
import os
import cv2
import matplotlib.pyplot as plt
import numpy as np
import dlib
일반적인 사진으로 고양이 수염 붙이기
my_image_path = os.getenv('HOME') + '/aiffel/camera_sticker/images/IMG_0436.JPG'
img_bgr = cv2.imread(my_image_path) # OpenCV로 이미지를 불러옴.
img_show = img_bgr.copy() # 출력용 이미지를 따로 보관
plt.imshow(img_bgr) # 이미지를 출력하기 위해 출력할 이미지를 올려줌.
plt.show() # 이미지를 출력
# 색을 BGR 에서 RGB 변경
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
plt.imshow(img_rgb)
plt.show()
detector_hog = dlib.get_frontal_face_detector() # 기본 얼굴 감지기를 반환
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
dlib_rects = detector_hog(img_rgb, 1)
# 찾은 얼굴 영역 박스 리스트
print(dlib_rects)
for dlib_rect in dlib_rects: # 찾은 얼굴 영역의 좌표
l = dlib_rect.left() # 왼쪽
t = dlib_rect.top() # 위쪽
r = dlib_rect.right() # 오른쪽
b = dlib_rect.bottom() # 아래쪽
cv2.rectangle(img_show, (l,t), (r,b), (0,255,0), 2, lineType=cv2.LINE_AA) # 시작점의 좌표와 종료점 좌표로 직각 사각형을 그림
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
rectangles[[(2321, 1150) (3279, 2108)]]
model_path = os.getenv('HOME') + '/aiffel/camera_sticker/models/shape_predictor_68_face_landmarks.dat'
landmark_predictor = dlib.shape_predictor(model_path)
list_landmarks = []
for dlib_rect in dlib_rects:
points = landmark_predictor(img_rgb, dlib_rect)
list_points = list(map(lambda p: (p.x, p.y), points.parts()))
list_landmarks.append(list_points)
print(len(list_landmarks[0]))
68
for landmark in list_landmarks:
for point in landmark:
cv2.circle(img_show, point, 10, (0, 255, 255), -1)
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
for dlib_rect, landmark in zip(dlib_rects, list_landmarks): # 얼굴 영역을 저장하고 있는 값과 68개의 랜드마크를 저장하고 있는 값으로 반복문 실행
print (landmark[33]) # 코의 index는 33 입니다
x = landmark[33][0] # 이미지에서 코 부위의 x값
y = landmark[33][1]# 이미지에서 코 부위의 y값
w = h = dlib_rect.width() # 얼굴 사각형의 가로와 세로를 가지고 고양이 수염의 이미지 변경
print ('(x,y) : (%d,%d)'%(x,y))
print ('(w,h) : (%d,%d)'%(w,h))
(2790, 1805) (x,y) : (2790,1805) (w,h) : (959,959)
sticker_path = os.getenv('HOME')+'/aiffel/camera_sticker/images/cat-whiskers.png' # 고양이 수염 경로
img_sticker = cv2.imread(sticker_path) # 스티커 이미지를 불러옵니다
img_sticker = cv2.resize(img_sticker, (w,h)) # 스티커 이미지 조정
print (img_sticker.shape) # 사이즈를 조정한 고양이 수염 이미지의 차원 확인
(959, 959, 3)
# 고양이 수염의 x, y를 시작점을 다시 잡아줌.
refined_x = x - w // 2
refined_y = y - h //2
print ('(x,y) : (%d,%d)'%(refined_x, refined_y))
(x,y) : (2311,1326)
# 고양이 수염 스티커 붙임.
sticker_area = img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]]
img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]] = \
np.where(img_sticker==0,img_sticker,sticker_area).astype(np.uint8)
plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
plt.show()
고양이 수염 흐리게 붙이기.
my_image_path = os.getenv('HOME') + '/aiffel/camera_sticker/images/IMG_0605.JPG'
img_bgr = cv2.imread(my_image_path)
img_show = img_bgr.copy()
plt.imshow(img_bgr)
plt.show()
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
plt.imshow(img_rgb)
plt.show()
detector_hog = dlib.get_frontal_face_detector()
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
dlib_rects = detector_hog(img_rgb, 1)
print(dlib_rects)
for dlib_rect in dlib_rects: # 찾은 얼굴 영역의 좌표
l = dlib_rect.left() # 왼쪽
t = dlib_rect.top() # 위쪽
r = dlib_rect.right() # 오른쪽
b = dlib_rect.bottom() # 아래쪽
cv2.rectangle(img_show, (l,t), (r,b), (0,255,0), 2, lineType=cv2.LINE_AA) # 시작점의 좌표와 종료점 좌표로 직각 사각형을 그림
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
rectangles[[(2147, 613) (3297, 1764)]]
model_path = os.getenv('HOME') + '/aiffel/camera_sticker/models/shape_predictor_68_face_landmarks.dat'
landmark_predictor = dlib.shape_predictor(model_path)
list_landmarks = []
for dlib_rect in dlib_rects:
points = landmark_predictor(img_rgb, dlib_rect)
list_points = list(map(lambda p: (p.x, p.y), points.parts()))
list_landmarks.append(list_points)
print(len(list_landmarks[0]))
68
for landmark in list_landmarks:
for point in landmark:
cv2.circle(img_show, point, 10, (0, 255, 255), -1)
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
# RGB 이미지로 전환
plt.imshow(img_show_rgb)
# 이미지를 준비
plt.show()
# 이미지를 출력
for dlib_rect, landmark in zip(dlib_rects, list_landmarks): # 얼굴 영역을 저장하고 있는 값과 68개의 랜드마크를 저장하고 있는 값으로 반복문 실행
print (landmark[33])
x = landmark[33][0]
y = landmark[33][1]
w =h= dlib_rect.width()
print ('(x,y) : (%d,%d)'%(x,y))
print ('(w,h) : (%d,%d)'%(w,h))
(2694, 1383) (x,y) : (2694,1383) (w,h) : (1151,1151)
sticker_path = os.getenv('HOME')+'/aiffel/camera_sticker/images/cat-whiskers.png'
img_sticker = cv2.imread(sticker_path)
img_sticker = cv2.resize(img_sticker, (w,h))
print (img_sticker.shape)
(1151, 1151, 3)
refined_x = x - w // 2
refined_y = y - h //2
print ('(x,y) : (%d,%d)'%(refined_x, refined_y))
(x,y) : (2119,808)
흐리게 만들기
- cv2.addWeighted(sticker_area,0.5,np.where(img_sticker==0,img_sticker,sticker_area).astype(np.uint8), 0.5, 0)을 사용해서 흐리게 만들었다.
sticker_area = img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]]
img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]] = \
cv2.addWeighted(sticker_area,0.5,np.where(img_sticker==0,img_sticker,sticker_area).astype(np.uint8), 0.5, 0)
plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
plt.show()
측면 사진으로 고양이 수염 붙이기
my_image_path = os.getenv('HOME') + '/aiffel/camera_sticker/images/IMG_0889.JPG'
img_bgr = cv2.imread(my_image_path)
img_show = img_bgr.copy()
plt.imshow(img_bgr)
plt.show()
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
plt.imshow(img_rgb)
plt.show()
detector_hog = dlib.get_frontal_face_detector()
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
dlib_rects = detector_hog(img_rgb, 1)
print(dlib_rects)
for dlib_rect in dlib_rects: # 찾은 얼굴 영역의 좌표
l = dlib_rect.left() # 왼쪽
t = dlib_rect.top() # 위쪽
r = dlib_rect.right() # 오른쪽
b = dlib_rect.bottom() # 아래쪽
cv2.rectangle(img_show, (l,t), (r,b), (0,255,0), 2, lineType=cv2.LINE_AA) # 시작점의 좌표와 종료점 좌표로 직각 사각형을 그림
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
rectangles[[(2013, 1211) (2281, 1479)]]
model_path = os.getenv('HOME') + '/aiffel/camera_sticker/models/shape_predictor_68_face_landmarks.dat'
landmark_predictor = dlib.shape_predictor(model_path)
list_landmarks = []
for dlib_rect in dlib_rects:
points = landmark_predictor(img_rgb, dlib_rect)
list_points = list(map(lambda p: (p.x, p.y), points.parts()))
list_landmarks.append(list_points)
print(len(list_landmarks[0]))
68
for landmark in list_landmarks:
for point in landmark:
cv2.circle(img_show, point, 10, (0, 255, 255), -1)
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
for dlib_rect, landmark in zip(dlib_rects, list_landmarks):
print (landmark[33])
x = landmark[33][0]
y = landmark[33][1]
w =h= dlib_rect.width()
print ('(x,y) : (%d,%d)'%(x,y))
print ('(w,h) : (%d,%d)'%(w,h))
(2174, 1372) (x,y) : (2174,1372) (w,h) : (269,269)
sticker_path = os.getenv('HOME')+'/aiffel/camera_sticker/images/cat-whiskers.png'
img_sticker = cv2.imread(sticker_path)
img_sticker = cv2.resize(img_sticker, (w,h))
print (img_sticker.shape)
(269, 269, 3)
refined_x = x - w // 2
refined_y = y - h //2
print ('(x,y) : (%d,%d)'%(refined_x, refined_y))
(x,y) : (2040,1238)
sticker_area = img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]]
img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]] = \
np.where(img_sticker==0,img_sticker,sticker_area).astype(np.uint8)
plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
plt.show()
-
측면으로 했을때, 살짝 고양이 수염이 옆으로 틀어지지 않았지만 멀리있는 얼굴이라서 조금 괜찮아 보였던 것 같다.
-
광대 쪽에 있는 landmark 사이의 길이 비율을 보고 고양이 수염의 높이의 비율을 조정하면 입체적으로 고양이 수염이 붙여질 거라 생각한다.
고개를 숙인 사진(얼굴 각도)에 고양이 수염 붙이기
my_image_path = os.getenv('HOME') + '/aiffel/camera_sticker/images/IMG_1075.JPG'
img_bgr = cv2.imread(my_image_path)
img_show = img_bgr.copy()
plt.imshow(img_bgr)
plt.show()
detector_hog = dlib.get_frontal_face_detector()
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
dlib_rects = detector_hog(img_rgb, 1)
print(dlib_rects)
for dlib_rect in dlib_rects: # 찾은 얼굴 영역의 좌표
l = dlib_rect.left() # 왼쪽
t = dlib_rect.top() # 위쪽
r = dlib_rect.right() # 오른쪽
b = dlib_rect.bottom() # 아래쪽
cv2.rectangle(img_show, (l,t), (r,b), (0,255,0), 2, lineType=cv2.LINE_AA)
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
rectangles[[(1529, 1016) (1991, 1478)]]
model_path = os.getenv('HOME') + '/aiffel/camera_sticker/models/shape_predictor_68_face_landmarks.dat'
landmark_predictor = dlib.shape_predictor(model_path)
list_landmarks = []
for dlib_rect in dlib_rects:
points = landmark_predictor(img_rgb, dlib_rect)
list_points = list(map(lambda p: (p.x, p.y), points.parts()))
list_landmarks.append(list_points)
print(len(list_landmarks[0]))
68
for landmark in list_landmarks:
for point in landmark:
cv2.circle(img_show, point, 10, (0, 255, 255), -1)
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
for dlib_rect, landmark in zip(dlib_rects, list_landmarks):
print (landmark[33])
x = landmark[33][0]
y = landmark[33][1]
w =h= dlib_rect.width()
print ('(x,y) : (%d,%d)'%(x,y))
print ('(w,h) : (%d,%d)'%(w,h))
import math
tan = (landmark[30][0]-landmark[27][0])/(landmark[30][1]-landmark[27][1])
theta = np.arctan(tan)
rotate_angle = theta *180/math.pi
print(rotate_angle)
(1764, 1307) (x,y) : (1764,1307) (w,h) : (463,463) -30.183680657222354
sticker_path = os.getenv('HOME')+'/aiffel/camera_sticker/images/cat-whiskers.png'
img_sticker = cv2.imread(sticker_path)
img_sticker = cv2.resize(img_sticker, (w,h))
print (img_sticker.shape)
(463, 463, 3)
refined_x = x - w // 2
refined_y = y - h //2
print ('(x,y) : (%d,%d)'%(refined_x, refined_y))
sticker_area = img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]]
img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]] = \
np.where(img_sticker==0,img_sticker,sticker_area).astype(np.uint8)
plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
plt.show()
(x,y) : (1533,1076)
- 회전 함수를 적용하지 않을 때, 고양이 수염이 제대로 붙여있지 않다.
import math
tan = (landmark[30][0]-landmark[27][0])/(landmark[30][1]-landmark[27][1])
theta = np.arctan(tan)
rotate_angle = theta *180/math.pi
print(rotate_angle)
-30.183680657222354
def rotate_image(image, angle):
image_center = tuple(np.array(image.shape[1::-1]) / 2)
rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0)
result = cv2.warpAffine(image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR,borderValue=(255,255,255))
return result
img_rotate = rotate_image(img_sticker,rotate_angle)
print(img_rotate.shape)
plt.imshow(img_rotate)
plt.show()
(463, 463, 3)
refined_x = x - w // 2
refined_y = y - h//2
print ('(x,y) : (%d,%d)'%(refined_x, refined_y))
sticker_area = img_bgr[refined_y:refined_y +img_rotate.shape[0], refined_x:refined_x+img_rotate.shape[1]]
img_bgr[refined_y:refined_y +img_rotate.shape[0], refined_x:refined_x+img_rotate.shape[1]] = np.where(img_rotate==255,sticker_area, img_rotate).astype(np.uint8)
plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
plt. show()
(x,y) : (1533,1076)
- 회전 함수(rotate_image)를 만들어 코의 기둥을 tan값을 구하고 그 각을 알기위해 arctan을 구했다. 그 각도 만큼 고양이 수염을 회전시켜 고개의 각도에 따라 고양이 수염이 회전하여 붙여지는 것을 확인할 수 있다.
어두운 사진에 고양이 수염 붙이기
my_image_path = os.getenv('HOME') + '/aiffel/camera_sticker/images/IMG_0952.JPG'
img_bgr = cv2.imread(my_image_path)
img_show = img_bgr.copy()
plt.imshow(img_bgr)
plt.show()
detector_hog = dlib.get_frontal_face_detector()
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
dlib_rects = detector_hog(img_rgb, 1)
print(dlib_rects)
for dlib_rect in dlib_rects: # 찾은 얼굴 영역의 좌표
l = dlib_rect.left() # 왼쪽
t = dlib_rect.top() # 위쪽
r = dlib_rect.right() # 오른쪽
b = dlib_rect.bottom() # 아래쪽
cv2.rectangle(img_show, (l,t), (r,b), (0,255,0), 2, lineType=cv2.LINE_AA) # 시작점의 좌표와 종료점 좌표로 직각 사각형을 그림
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
rectangles[[(2844, 1311) (3165, 1632)], [(2193, 1326) (2229, 1362)]]
- 위에서 사각형이 2개가 나온 것을 확인하고, 어둡고 복잡한 배경때문에 얼굴로 인식했을 수 있겠다는 생각을 했다.
model_path = os.getenv('HOME') + '/aiffel/camera_sticker/models/shape_predictor_68_face_landmarks.dat'
landmark_predictor = dlib.shape_predictor(model_path)
list_landmarks = []
for dlib_rect in dlib_rects:
points = landmark_predictor(img_rgb, dlib_rect)
list_points = list(map(lambda p: (p.x, p.y), points.parts()))
list_landmarks.append(list_points)
print(len(list_landmarks[0]))
68
# 배경 이미지에도 landmark가 새겨질 것이다.
for landmark in list_landmarks:
for point in landmark:
cv2.circle(img_show, point, 10, (0, 255, 255), -1)
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
sticker_path = os.getenv('HOME')+'/aiffel/camera_sticker/images/cat-whiskers.png'
img_sticker = cv2.imread(sticker_path)
for dlib_rect, landmark in zip(dlib_rects, list_landmarks):
print (landmark[33])
x = landmark[33][0]
y = landmark[33][1]
w =h= dlib_rect.width()
print ('(x,y) : (%d,%d)'%(x,y))
print ('(w,h) : (%d,%d)'%(w,h))
refined_x = x - w // 2
refined_y = y - h //2
img_sticker = cv2.resize(img_sticker, (w,h))
print (img_sticker.shape)
print ('(x,y) : (%d,%d)'%(refined_x, refined_y))
sticker_area = img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]]
img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]] = \
np.where(img_sticker==0,img_sticker,sticker_area).astype(np.uint8)
plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
plt.show()
(3004, 1522) (x,y) : (3004,1522) (w,h) : (322,322) (322, 322, 3) (x,y) : (2843,1361) (2215, 1351) (x,y) : (2215,1351) (w,h) : (37,37) (37, 37, 3) (x,y) : (2197,1333)
- 배경이미지에 사람 얼굴을 인식해 반복문을 넣어 실제 얼굴에 고양이 수염을 넣을 수 있었다.
멀리있는 얼굴에 고양이 수염 붙이기
my_image_path = os.getenv('HOME') + '/aiffel/camera_sticker/images/IMG_0882.JPG'
img_bgr = cv2.imread(my_image_path)
img_show = img_bgr.copy()
plt.imshow(img_bgr)
plt.show()
detector_hog = dlib.get_frontal_face_detector()
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
dlib_rects = detector_hog(img_rgb, 1)
print(dlib_rects)
for dlib_rect in dlib_rects: # 찾은 얼굴 영역의 좌표
l = dlib_rect.left() # 왼쪽
t = dlib_rect.top() # 위쪽
r = dlib_rect.right() # 오른쪽
b = dlib_rect.bottom() # 아래쪽
cv2.rectangle(img_show, (l,t), (r,b), (0,255,0), 2, lineType=cv2.LINE_AA) # 시작점의 좌표와 종료점 좌표로 직각 사각형을 그림
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
rectangles[[(1480, 1460) (1666, 1646)]]
model_path = os.getenv('HOME') + '/aiffel/camera_sticker/models/shape_predictor_68_face_landmarks.dat'
landmark_predictor = dlib.shape_predictor(model_path)
list_landmarks = []
for dlib_rect in dlib_rects:
points = landmark_predictor(img_rgb, dlib_rect)
list_points = list(map(lambda p: (p.x, p.y), points.parts()))
list_landmarks.append(list_points)
print(len(list_landmarks[0]))
68
for landmark in list_landmarks:
for point in landmark:
cv2.circle(img_show, point, 10, (0, 255, 255), -1)
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
sticker_path = os.getenv('HOME')+'/aiffel/camera_sticker/images/cat-whiskers.png'
img_sticker = cv2.imread(sticker_path)
for dlib_rect, landmark in zip(dlib_rects, list_landmarks):
print (landmark[33])
x = landmark[33][0]
y = landmark[33][1]
w =h= dlib_rect.width()
print ('(x,y) : (%d,%d)'%(x,y))
print ('(w,h) : (%d,%d)'%(w,h))
refined_x = x - w // 2
refined_y = y - h //2
img_sticker = cv2.resize(img_sticker, (w,h))
print (img_sticker.shape)
print ('(x,y) : (%d,%d)'%(refined_x, refined_y))
sticker_area = img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]]
img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]] = \
np.where(img_sticker==0,img_sticker,sticker_area).astype(np.uint8)
plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
plt.show()
(1567, 1573) (x,y) : (1567,1573) (w,h) : (187,187) (187, 187, 3) (x,y) : (1474,1480)
- 멀리있는 사진도 고양이 수염이 얼굴 사이즈에 맞게 잘 붙는 것 같다.
두 명 사진에 고양이 수염 붙이기
my_image_path = os.getenv('HOME') + '/aiffel/camera_sticker/images/IMG_9599.JPG'
img_bgr = cv2.imread(my_image_path)
img_show = img_bgr.copy()
plt.imshow(img_bgr)
plt.show()
detector_hog = dlib.get_frontal_face_detector()
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
dlib_rects = detector_hog(img_rgb, 1)
print(dlib_rects)
for dlib_rect in dlib_rects: # 찾은 얼굴 영역의 좌표
l = dlib_rect.left() # 왼쪽
t = dlib_rect.top() # 위쪽
r = dlib_rect.right() # 오른쪽
b = dlib_rect.bottom() # 아래쪽
cv2.rectangle(img_show, (l,t), (r,b), (0,255,0), 3, lineType=cv2.LINE_AA) # 시작점의 좌표와 종료점 좌표로 직각 사각형을 그림
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
rectangles[[(191, 937) (1149, 1895)], [(1632, 1067) (2094, 1530)]]
model_path = os.getenv('HOME') + '/aiffel/camera_sticker/models/shape_predictor_68_face_landmarks.dat'
landmark_predictor = dlib.shape_predictor(model_path)
list_landmarks = []
for dlib_rect in dlib_rects:
points = landmark_predictor(img_rgb, dlib_rect)
list_points = list(map(lambda p: (p.x, p.y), points.parts()))
list_landmarks.append(list_points)
print(len(list_landmarks[0]))
68
for landmark in list_landmarks:
for point in landmark:
cv2.circle(img_show, point, 10, (0, 255, 255), -1)
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
sticker_path = os.getenv('HOME')+'/aiffel/camera_sticker/images/cat-whiskers.png'
img_sticker = cv2.imread(sticker_path)
for dlib_rect, landmark in zip(dlib_rects, list_landmarks):
print (landmark[33])
x = landmark[33][0]
y = landmark[33][1]
w =h= dlib_rect.width()
print ('(x,y) : (%d,%d)'%(x,y))
print ('(w,h) : (%d,%d)'%(w,h))
img_sticker = cv2.resize(img_sticker, (w,h))
tan = (landmark[30][0]-landmark[27][0])/(landmark[30][1]-landmark[27][1])
theta = np.arctan(tan)
rotate_angle = theta *180/math.pi
print(rotate_angle)
img_rotate = rotate_image(img_sticker,rotate_angle)
refined_x = x - w // 2
refined_y = y - h //2
print ('(x,y) : (%d,%d)'%(refined_x, refined_y))
sticker_area = img_bgr[refined_y:refined_y +img_rotate.shape[0], refined_x:refined_x+img_rotate.shape[1]]
img_bgr[refined_y:refined_y +img_rotate.shape[0], refined_x:refined_x+img_rotate.shape[1]] = \
cv2.addWeighted(sticker_area,0.5,np.where(img_rotate==0,img_rotate,sticker_area).astype(np.uint8), 0.5, 0)
plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
plt.show()
(690, 1569) (x,y) : (690,1569) (w,h) : (959,959) -8.866676044144272 (x,y) : (211,1090) (1849, 1374) (x,y) : (1849,1374) (w,h) : (463,463) -16.886791123944043 (x,y) : (1618,1143)
- 얼굴의 각도에 따라 고양이 수염을 회전시켜서 붙였다.
세 명 사진에 고양이 수염 붙이기
my_image_path = os.getenv('HOME') + '/aiffel/camera_sticker/images/IMG_2569.JPG'
img_bgr = cv2.imread(my_image_path)
img_show = img_bgr.copy()
plt.imshow(img_bgr)
plt.show()
detector_hog = dlib.get_frontal_face_detector()
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
dlib_rects = detector_hog(img_rgb, 1)
print(dlib_rects)
for dlib_rect in dlib_rects: # 찾은 얼굴 영역의 좌표
l = dlib_rect.left() # 왼쪽
t = dlib_rect.top() # 위쪽
r = dlib_rect.right() # 오른쪽
b = dlib_rect.bottom() # 아래쪽
cv2.rectangle(img_show, (l,t), (r,b), (0,255,0), 3, lineType=cv2.LINE_AA)
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
rectangles[[(740, 491) (1061, 812)], [(1256, 724) (2214, 1682)], [(247, 418) (632, 804)]]
model_path = os.getenv('HOME') + '/aiffel/camera_sticker/models/shape_predictor_68_face_landmarks.dat'
landmark_predictor = dlib.shape_predictor(model_path)
list_landmarks = []
for dlib_rect in dlib_rects:
points = landmark_predictor(img_rgb, dlib_rect)
list_points = list(map(lambda p: (p.x, p.y), points.parts()))
list_landmarks.append(list_points)
print(len(list_landmarks[0]))
68
for landmark in list_landmarks:
for point in landmark:
cv2.circle(img_show, point, 10, (0, 255, 255), -1)
img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
sticker_path = os.getenv('HOME')+'/aiffel/camera_sticker/images/cat-whiskers.png'
img_sticker = cv2.imread(sticker_path)
고양이 수염을 회전 시켰을 때 사진
for dlib_rect, landmark in zip(dlib_rects, list_landmarks):
print (landmark[33])
x = landmark[33][0]
y = landmark[33][1]
w =h= dlib_rect.width()
print ('(x,y) : (%d,%d)'%(x,y))
print ('(w,h) : (%d,%d)'%(w,h))
img_sticker = cv2.resize(img_sticker, (w,h))
tan = (landmark[30][0]-landmark[27][0])/(landmark[30][1]-landmark[27][1])
theta = np.arctan(tan)
rotate_angle = theta *180/math.pi
print(rotate_angle)
img_rotate = rotate_image(img_sticker,rotate_angle)
refined_x = x - w // 2
refined_y = y - h //2
print ('(x,y) : (%d,%d)'%(refined_x, refined_y))
sticker_area = img_bgr[refined_y:refined_y +img_rotate.shape[0], refined_x:refined_x+img_rotate.shape[1]]
img_bgr[refined_y:refined_y +img_rotate.shape[0], refined_x:refined_x+img_rotate.shape[1]] = \
cv2.addWeighted(sticker_area,0.5,np.where(img_rotate==0,img_rotate,sticker_area).astype(np.uint8), 0.5, 0)
plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
plt.show()
(902, 669) (x,y) : (902,669) (w,h) : (322,322) -4.1849161251184155 (x,y) : (741,508) (1746, 1257) (x,y) : (1746,1257) (w,h) : (959,959) -4.283818526272696 (x,y) : (1267,778) (482, 669) (x,y) : (482,669) (w,h) : (386,386) -3.6522227803063356 (x,y) : (289,476)
고양이 수염을 회전 시키지 않았을 때 사진
for dlib_rect, landmark in zip(dlib_rects, list_landmarks):
print (landmark[33])
x = landmark[33][0]
y = landmark[33][1]
w =h= dlib_rect.width()
print ('(x,y) : (%d,%d)'%(x,y))
print ('(w,h) : (%d,%d)'%(w,h))
img_sticker = cv2.resize(img_sticker, (w,h))
#tan = (landmark[30][0]-landmark[27][0])/(landmark[30][1]-landmark[27][1])
#theta = np.arctan(tan)
#rotate_angle = theta *180/math.pi
#print(rotate_angle)
#img_rotate = rotate_image(img_sticker,rotate_angle)
refined_x = x - w // 2
refined_y = y - h //2
print ('(x,y) : (%d,%d)'%(refined_x, refined_y))
sticker_area = img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]]
img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]] = \
cv2.addWeighted(sticker_area,0.5,np.where(img_sticker==0,img_sticker,sticker_area).astype(np.uint8), 0.5, 0)
plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
plt.show()
(902, 669) (x,y) : (902,669) (w,h) : (322,322) (x,y) : (741,508) (1746, 1257) (x,y) : (1746,1257) (w,h) : (959,959) (x,y) : (1267,778) (482, 669) (x,y) : (482,669) (w,h) : (386,386) (x,y) : (289,476)
-
고양이 수염의 회전을 생각해서 회전 함수를 사용했지만, 실제로 고양이 수염을 붙였을때 모습이 조금 비뚤어져 보였다.
-
사람의 코의 각도가 다를 수 있고, 사진에 찍힌 얼굴 각도에 따라도 고양이 수염 회전 함수의 각도가 유용하게 작용하지 않는 것을 알 수 있었다.
회고
-
어려웠던 점 : cv2.addWeighted을 적용하는 부분이 어려웠다. 사진의 밝기를 조절하는 법이 어려워서 밝았을때, 얼굴을 인식할 수 있는지에 대해서는 확인하지 못했지만, 어두울 때 사람 얼굴을 인식하고 고양이 수염도 붙일 수 있으니 밝았을때도 가능할거라 생각한다.
-
알아낸 점 및 모호한 점 : 고양이 수염을 회전시켰을 때 함수를 따로 구현할 수 있다는 것을 알아냈다.
-
노력한 점 : 얼굴 각도에 따른 고양이 수염을 붙이는 법을 해냈다.
-
자기다짐 : 얼굴이 옆으로 틀어졌을 때, 고양이 수염이 입체적으로 보이도록 붙이는 방법을 찾아서 적용하고 싶다. 각각의 구현한 것을 함수로 짠다면, 일일이 복사해서 사용하지 않을거라 생각한다.
Subscribe via RSS